package cn.sciento.farm.devicemanager.service.impl;

import cn.sciento.farm.devicemanager.dao.entity.DevController;
import cn.sciento.farm.devicemanager.dao.entity.DevDevice;
import cn.sciento.farm.devicemanager.dao.mapper.ControllerMapper;
import cn.sciento.farm.devicemanager.gateway.model.uplink.ControlData;
import cn.sciento.farm.devicemanager.service.ControllerService;
import cn.sciento.farm.devicemanager.service.DeviceService;
import cn.sciento.farm.devicemanager.service.TimerService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ControllerServiceImpl implements ControllerService {

    @Autowired
    private ControllerMapper controllerMapper;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private TimerService timerService;

    // todo 这个代码有问题
    @Override
    public int updateOnline(String eui, String node, String  circuit, int up) {

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("eui",eui);
        if(StringUtils.isNotEmpty(node)){
            queryWrapper.eq("node",node);
        }
        if(StringUtils.isNotEmpty(circuit)){
            queryWrapper.eq("circuit",circuit);
        }
        DevController devController = new DevController();
        devController.setOnline(up);
        int count = controllerMapper.update(devController,queryWrapper);
        return count;
    }

    @Override
    public DevController getByArg(String eui, String node, String circuit) {
        QueryWrapper queryWrapper = new QueryWrapper<DevController>();
        queryWrapper.eq("eui",eui);
        if(StringUtils.isEmpty(node)){
            queryWrapper.isNull("node");
        }else {
            queryWrapper.eq("node",node);
        }
        queryWrapper.eq("circuit",circuit);
        return controllerMapper.selectOne(queryWrapper);
    }

    @Override
    public int insert(DevController deviceSwitch) {
        QueryWrapper queryWrapper = new QueryWrapper<DevController>();
        queryWrapper.eq("eui",deviceSwitch.getEui());
        List<DevController> byEui = controllerMapper.selectList(queryWrapper);
        for (DevController devController : byEui) {
            if (devController.getName().equals(deviceSwitch.getName())) {
                controllerMapper.deleteById(devController.getId());
            }
        }
        return controllerMapper.insert(deviceSwitch);
    }

    @Override
    public int updateStatus(ControlData switchStatus) {
        Date date = new Date();
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("eui",switchStatus.getEui());
        if(StringUtils.isNotEmpty(switchStatus.getNode())){
            queryWrapper.eq("node",switchStatus.getNode());
        }else {
            queryWrapper.isNull("node");
        }
        queryWrapper.eq("circuit",switchStatus.getCircuit());
        DevController devController = new DevController();
        devController.setLastTime(date.getTime());
        devController.setType(switchStatus.getDeviceType());
        devController.setWaterFeedback(switchStatus.getWaterFeedback());
        devController.setStatus(switchStatus.getEn());
        int count = controllerMapper.update(devController,queryWrapper);
        return count;
    }

    @Override
    public int updateById(DevController devController) {
        return controllerMapper.updateById(devController);
    }

    @Override
    public int deleteById(long id) {
        deleteTimer(id);
        return controllerMapper.deleteById(id);
    }

    @Override
    public List<DevController> getByEui(String eui) {
        QueryWrapper queryWrapper = new QueryWrapper<DevController>();
        queryWrapper.eq("eui",eui);
        queryWrapper.orderByDesc("sequence","create_time");
        List<DevController> controllerList = controllerMapper.selectList(queryWrapper);
        return getDeviceLimit(controllerList);
    }

    @Override
    public DevController getById(long id) {
        return controllerMapper.selectById(id);
    }

    @Override
    public List<DevController> getSameNode(long id) {
        DevController devController = getById(id);
        if(devController == null){
            return new ArrayList<>();
        }else {
            QueryWrapper queryWrapper= new QueryWrapper<DevController>();
            queryWrapper.eq("eui",devController.getEui());
            queryWrapper.eq("node",devController.getNode());
            List<DevController> controllerList = controllerMapper.selectList(queryWrapper);
            controllerList.removeIf(controller -> controller.getId().equals(id));
            return controllerList;
        }
    }

    @Override
    public List<DevController> getByLandId(int landId) {
        List<DevDevice> devDeviceList = deviceService.getByLandId(landId);
        List<String> idList = devDeviceList.stream().map(item->item.getId()).collect(Collectors.toList());
        List<DevController> controllerList = new ArrayList<>();
        if(idList.size() > 0){
            QueryWrapper queryWrapper = new QueryWrapper<DevController>();
            queryWrapper.in("eui",idList);
            queryWrapper.orderByDesc("sequence","create_time");
            controllerList = controllerMapper.selectList(queryWrapper);
        }
        return getDeviceLimit(controllerList);
    }

    private int deleteTimer(Long id){
        return timerService.deleteByControllerId(id);
    }

    @Override
    public int deleteByEui(String eui) {
        QueryWrapper queryWrapper = new QueryWrapper<DevController>();
        queryWrapper.eq("eui",eui);
        List<DevController> devControllerList = controllerMapper.selectList(queryWrapper);
        devControllerList.stream().forEach(controller -> {
            deleteTimer(controller.getId());
        });

        return controllerMapper.delete(queryWrapper);
    }

    @Override
    public void changeOnline(DevController devController) {
        controllerMapper.updateById(devController);
    }

    @Override
    public List<DevController> getListByLimit(long pageNo, int pageSize) {
        IPage<DevController> page = controllerMapper.selectPage(new Page<>(pageNo, pageSize), null);
        List<DevController> records = page.getRecords();
        return records;
    }

    @Override
    public int getCount() {
        return controllerMapper.selectCount(null);
    }


    private List<DevController> getDeviceLimit(List<DevController> deviceSwitches) {
        List<DevController> relateSwtichs = new ArrayList<>();
        List<DevController> baseSwitchs = new ArrayList<>();
        for (DevController deviceSwitch : deviceSwitches) {
            if (deviceSwitch.getRelatedEquip() == 0) {
                baseSwitchs.add(deviceSwitch);
            } else {
                relateSwtichs.add(deviceSwitch);
            }
        }
        for (DevController deviceSwitch : relateSwtichs) {
            long relatedSwitchId = deviceSwitch.getRelatedEquip();
            DevController relatedSwitch = null;
            int index = -1;
            for (int i = 0; i < baseSwitchs.size(); i++) {
                if (baseSwitchs.get(i).getId().equals(relatedSwitchId)) {
                    relatedSwitch = baseSwitchs.get(i);
                    index = i;
                    break;
                }
            }
            if (relatedSwitch != null) {
                int relateSwitchStatus = deviceSwitch.getStatus();
                int relatedSwitchStatus = relatedSwitch.getStatus();
                if (relateSwitchStatus == 0 && relatedSwitchStatus == 1) {
                    deviceSwitch.setStatus(2);
                }
                baseSwitchs.remove(index);
            }

        }
        // TODO 这里应该有个排序
        relateSwtichs.addAll(baseSwitchs);
        return relateSwtichs;
    }
}
